﻿using Entity;
using Entity.Sale;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using ServiceCore;
using ServiceCore.Token;
using ServiceCore.Tool;
using ServiceCore.Tool.Dapper;
using ServiceCore.Tool.ES;
using ServiceCore.Tool.MongoDB;
using ServiceCore.Tool.Pic;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Customer.Bussiness_Service
{
    public interface IToole_DI
    {
        IDapper_Helper di_db { get; }
        ISnowflake_Helper di_getid { get; }
        ITokenUser_Service di_user { get; }
        IHttpContextAccessor di_httpContextAccessor { get; }
        ICacheHelper di_cache { get; }
        IEs_Log_Helper di_es { get; }
        string get_Ip { get; }
        ResultObjModel GetEnum(List<string> Str);

        IConfiguration di_appSettingConfig { get; }

        string NumToChinese(string x);

        string[] search_workorder_Item { get; }

        void AddCmdLog(Mch_CMD_Log MchLog);
        ResultModel UpdateCmdLog(string id, string remark, string url);

        List<materiel_type> get_materiel_list { get; }

        void ref_materiel_list();
        /// <summary>
        /// 请求一次
        /// </summary>
        /// <param name="now_count"></param>
        void get_materiel_no_queue_in(int? now_count = null);
        /// <summary>
        /// 取一个
        /// </summary>
        int get_materiel_no_queue_out { get; }

        List<warehouse_base> get_warehouse_list { get; }
        void ref_warehouse_list();
    }
    /// <summary>
    /// 注入工具类
    /// </summary>
    public class Toole_DI : IToole_DI
    {
        /// <summary>
        /// 暴露注入点
        /// </summary>
        /// <param name="db"></param>
        /// <param name="getid"></param>
        /// <param name="httpContextAccessor"></param>
        /// <param name="user"></param>
        /// <param name="cache"></param>
        /// <param name="es"></param> 
        public Toole_DI(IDapper_Helper db, ISnowflake_Helper getid, IHttpContextAccessor httpContextAccessor, ITokenUser_Service user, ICacheHelper cache, IEs_Log_Helper es, IConfiguration AppSettingConfig)
        {
            di_db = db;
            di_getid = getid;
            di_httpContextAccessor = httpContextAccessor;
            di_user = user;
            di_cache = cache;
            di_es = es;
            di_appSettingConfig = AppSettingConfig;
        }

        public IConfiguration di_appSettingConfig { get; }
        /// <summary>
        /// dapper相关方法
        /// </summary>
        public IDapper_Helper di_db { get; }
        /// <summary>
        /// 雪花算法相关方法
        /// </summary>
        public ISnowflake_Helper di_getid { get; }
        /// <summary>
        /// 获取当前登录用户方法
        /// </summary>
        public ITokenUser_Service di_user { get; }
        /// <summary>
        /// 调用当前访问上下文方法
        /// </summary>
        public IHttpContextAccessor di_httpContextAccessor { get; }
        /// <summary>
        /// 注册缓存类
        /// </summary>
        public ICacheHelper di_cache { get; }
        /// <summary>
        /// ES日志方法
        /// </summary>
        public IEs_Log_Helper di_es { get; }

        public string get_Ip
        {
            get
            {
                return di_httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
            }
        }


        /// <summary>
        /// 获取枚举信息
        /// </summary>
        /// <returns></returns> 
        public ResultObjModel GetEnum(List<string> Str)
        {
            return CoreStartDo.ResultAction(result =>
            {
                List<object> result_obj = new List<object>();
                foreach (var item in Str)
                {

                    switch (item)
                    {
                        case "repair_handle_state":
                            result_obj.Add(GetEnumItem<repair_handle_state>());
                            break;

                        case "apply_state":
                            result_obj.Add(GetEnumItem<apply_state>());
                            break;
                        case "Mch_Type":
                            result_obj.Add(GetEnumItem<Mch_Type>());
                            break;
                        case "user_source":
                            result_obj.Add(GetEnumItem<user_source>());
                            break;
                        case "sale_work_state_enum":
                            result_obj.Add(GetEnumItem<sale_work_state_enum>());
                            break;
                        case "work_order_approval":
                            result_obj.Add(GetEnumItem<work_order_approval>());
                            break;
                        case "work_state":
                            result_obj.Add(GetEnumItem<work_state>());
                            break;
                        case "logistics_state":
                            result_obj.Add(GetEnumItem<logistics_state>());
                            break;
                        case "card_state":
                            result_obj.Add(GetEnumItem<card_state>());
                            break;
                        case "record_type":
                            result_obj.Add(GetEnumItem<record_type>());
                            break;
                    }
                }
                result.code = 0;
                result.msg = "Success";
                result.data = result_obj;
                return result;
            });
        }
        /// <summary>
        /// 获取枚举
        /// </summary>
        /// <returns></returns>
        private object GetEnumItem<T>()
        {
            List<object> KidEnum = new List<object>();
            foreach (var kiditem in Enum.GetValues(typeof(T)))
            {
                KidEnum.Add(new { id = kiditem, name = ((T)kiditem).ToString() });
            }
            return new { enumname = typeof(T).Name, data = KidEnum }; ;
        }
        #region 数字转换 
        /// <summary>
        /// 阿拉伯数字转换成中文数字
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public string NumToChinese(string x)
        {
            string[] pArrayNum = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
            //为数字位数建立一个位数组  
            string[] pArrayDigit = { "", "十", "百", "千" };
            //为数字单位建立一个单位数组  
            string[] pArrayUnits = { "", "万", "亿", "万亿" };
            var pStrReturnValue = ""; //返回值  
            var finger = 0; //字符位置指针  
            var pIntM = x.Length % 4; //取模  
            int pIntK;
            if (pIntM > 0)
                pIntK = x.Length / 4 + 1;
            else
                pIntK = x.Length / 4;
            //外层循环,四位一组,每组最后加上单位: ",万亿,",",亿,",",万,"  
            for (var i = pIntK; i > 0; i--)
            {
                var pIntL = 4;
                if (i == pIntK && pIntM != 0)
                    pIntL = pIntM;
                //得到一组四位数  
                var four = x.Substring(finger, pIntL);
                var P_int_l = four.Length;
                //内层循环在该组中的每一位数上循环  
                for (int j = 0; j < P_int_l; j++)
                {
                    //处理组中的每一位数加上所在的位  
                    int n = Convert.ToInt32(four.Substring(j, 1));
                    if (n == 0)
                    {
                        if (j < P_int_l - 1 && Convert.ToInt32(four.Substring(j + 1, 1)) > 0 && !pStrReturnValue.EndsWith(pArrayNum[n]))
                            pStrReturnValue += pArrayNum[n];
                    }
                    else
                    {
                        if (!(n == 1 && (pStrReturnValue.EndsWith(pArrayNum[0]) | pStrReturnValue.Length == 0) && j == P_int_l - 2))
                            pStrReturnValue += pArrayNum[n];
                        pStrReturnValue += pArrayDigit[P_int_l - j - 1];
                    }
                }
                finger += pIntL;
                //每组最后加上一个单位:",万,",",亿," 等  
                if (i < pIntK) //如果不是最高位的一组  
                {
                    if (Convert.ToInt32(four) != 0)
                        //如果所有4位不全是0则加上单位",万,",",亿,"等  
                        pStrReturnValue += pArrayUnits[i - 1];
                }
                else
                {
                    //处理最高位的一组,最后必须加上单位  
                    pStrReturnValue += pArrayUnits[i - 1];
                }
            }
            return pStrReturnValue;
        }
        #endregion

        #region 工单查询字段定义
        public string[] search_workorder_Item
        {
            get
            {
                return new string[] {
            "a.*","b.mch_name","b.mch_id","b.work_end_time","b.total_state","b.work_approval_state","b.work_state","b.logistics_state","b.send_time","b.province","b.city","b.district","b.address","c.template_name as slot_template_name","b.send_No"
            ,"b.baseusername","b.baseuserid","b.approval_end_time","b.approval_cloes_time","b.approval_back_time","b.work_get_time","b.create_order_time","b.working_time","b.QA_end_time","b.true_work_end_time","b.work_close_time","b.work_back_time"
                 };
            }
        }

        #endregion

        /// <summary>
        /// 新增一个指令日志
        /// </summary>
        public void AddCmdLog(Mch_CMD_Log MchLog)
        {
            try
            {
                MchLog.SendTime = DateTime.Now;
                MchLog.SendState = 0;
                di_db.do_rk_Execute(di_db.AddBySqlStr<Mch_CMD_Log>(), MchLog);//.Add(MchLog);
            }
            catch
            {

            }
        }
        /// <summary>
        /// 回报指令已接收
        /// </summary>
        /// <param name="id"></param>
        public ResultModel UpdateCmdLog(string id, string remark, string url)
        {
            return CoreStartDo.ResultAction<ResultModel>(result =>
            {
                int updaterow = di_db.do_rk_Execute("update Mch_CMD_Log set PostTime=@PostTime,ex_Url=@ex_Url,Remark = isnull(Remark, '') +@Remark+',',SendState=@SendState where Id=@Id", new { PostTime = DateTime.Now, ex_Url = url, Remark = remark, Id = id, SendState = 1 });
                if (updaterow > 0)
                {
                    result.code = 0;
                    result.msg = "Success";
                }
                else
                {
                    result.code = 1;
                    result.msg = "Fail";
                }
                return result;
            });
        }

        public static List<materiel_type> all_type = null;
        public List<materiel_type> get_materiel_list
        {
            get
            {
                if (all_type == null || !all_type.Any())
                {
                    all_type = di_db.GetList<materiel_type>("select * from materiel_type", null).ToList();
                }
                return all_type;
            }
        }
        public void ref_materiel_list()
        {
            all_type = di_db.GetList<materiel_type>("select * from materiel_type", null).ToList();
        }



        public static ConcurrentQueue<int> get_materiel_no_queue = new ConcurrentQueue<int>();
        /// <summary>
        /// 
        /// </summary>
        public void get_materiel_no_queue_in(int? now_count = null)
        {
            if (!now_count.HasValue)
            {
                now_count = di_db.GetList<int>("select count(*) from materiel_base", null).FirstOrDefault() + 1;
            }
            if (get_materiel_no_queue.Where(s => s == now_count.Value).Any())
            {
                get_materiel_no_queue_in(now_count++);
            }
            get_materiel_no_queue.Enqueue(now_count.Value);
        }
        public int get_materiel_no_queue_out
        {
            get
            {
                int result = -1;
                int try_count = 50;
                while (try_count > 0)
                {
                    if (get_materiel_no_queue.TryDequeue(out result))
                    { 
                        //拿到数据就中断循环 
                        break;
                    }
                    else { 
                        try_count--;
                    } 
                }
                return result;
            }
        }

        private List<warehouse_base> warehouse_list = null;
        public List<warehouse_base> get_warehouse_list
        {
            get
            {
                if (warehouse_list == null || !warehouse_list.Any())
                {
                    warehouse_list = di_db.GetList<warehouse_base>("select * from warehouse_base", null).ToList();
                }
                return warehouse_list;
            }
        }
        public void ref_warehouse_list()
        {
            warehouse_list = di_db.GetList<warehouse_base>("select * from warehouse_base", null).ToList();
        }
    }
}